10. Exercise: Coroutines and Deferred

6 Exercise Coroutines And Deferred-- 2020-

Note: Retrofit 2 Coroutine CallAdapter is Deprecated

Retrofit 2 Coroutine CallAdapter has become deprecated. It is recommended to migrate to Retrofit 2.6.0 or newer and use its built-in suspend support.
At timestamp 00:51 in the video above, in MapApiService.kt file, it shows using the deprecated addCallAdapterFactory(CoroutineCallAdapterFactory()). You do not need to include that line of code anymore. Since the CallAdapter is deprecated, we do not need to include the following coroutines dependencies in app/build.gradle as well:

    // Coroutines
    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$version_kotlin_coroutines"`
    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$version_kotlin_coroutines"
    // Retrofit Coroutines Support
    implementation "com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:$version_retrofit_coroutines_adapter"

Consequently, there are mild updates in the OverviewViewModel.kt, particularly the getMarsRealEstateProperties() function, as shown in the instructions below. You can also refer to the updated files in the relevant branch of the andfun-kotlin-mars-real-estate repo.

Now it's your turn to complete this exercise yourself!

In this lesson, you're going streamline your Retrofit API service by replacing the callback and interfaces with coroutines and exception handling. If you want to start at this step, you can download this exercise from: Step.03-Exercise-Using-Retrofit-With-Coroutines. You will find plenty of //TODO comments to help you complete things.

In MarsApiService.kt file:

  1. Change getProperties() Call<List<MarsProperty>> to a list of MarsProperty:
  @GET("realestate")
    suspend fun getProperties(): List<MarsProperty>



In OverviewViewModel.ktfile:

  1. Remember, creating own scope is no longer recommended by Google. Therefore, it is not required to add variable for a coroutine Job and a CoroutineScope using the Main Dispatcher anymore. Instead, you can use the default viewModelScope:
    // Not required
    // private var viewModelJob = Job()
    // private val coroutineScope = CoroutineScope(viewModelJob + Dispatchers.Main ) 


Consequently, we will not require to override onCleared() at the end of the OverviewViewModel.ktfile.


  1. In getMarsRealEstateProperties(), replace the enque() code with a viewModelScope for making the API request:
viewModelScope.launch {

 }



  1. Inside the viewModelScope, add a try/catch block, and catch a generic Exception.
try{
     var listResult = MarsApi.retrofitService.getProperties()
     _response.value = "Success: ${listResult.size} Mars properties retrieved"
}


Note: We will get the Deferred object for our Retrofit request inside the try block. Hence, we do not need a var getPropertiesDeferred = MarsApi.retrofitService.getProperties() before a try block..


  1. Then return the list size (as before) in the success message, and the message from the exception in the failure message.

    Your new getMarsRealEstateProperties() function should look like this:

    private fun getMarsRealEstateProperties() {
        viewModelScope.launch {          
            try {
                var listResult = MarsApi.retrofitService.getProperties()
                _response.value = "Success: ${listResult.size} Mars properties retrieved"
            } catch (e: Exception) {
                _response.value = "Failure: ${e.message}"
            }
        }
    }


  1. There is no need to override onCleared() function thats cancels the Job when the ViewModel is finished. This step is not required anymore.

Build and run your code and verify the app works exactly as it did before.

You can check your solution against the solution we’ve provided here: Step.03-Solution-Using-Retrofit-With-Coroutines, or using this git diff.

Task Description:

Complete the tasks below to launch retrofit requests in a coroutine.

Task List:

Task Feedback:

Good work!

Reference documentation